#include "ImageContainer.h"
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "DissimilarityMatrix.h"
#include "Utilities.h"
#include "AffineRansac.h"
#include "OrientedKruskal.h"
#include "UnionFindSet.h"

#include <iostream>
#include <cstring>
#include <unistd.h>

int main(int argc, char** argv)
{
	Mat A = (Mat_<uchar>(2, 2) << 1, 3, 6, 7);
	Mat B = (Mat_<uchar>(2, 2) << 2, 1, 8, 7);

	cout << "mse: " << meanSqrdError(A, B) << endl;

	double totaltime = (double)getTickCount();
	string bfname(argv[1]);
	string testName(argv[2]);
	string resultDir(argv[3]);

	cout << "running test: " << testName << endl;
	ImageContainer imCont = ImageContainer(bfname);
	imCont.ReadBaseFile();
	imCont.ReadImageDirectory();
    //imCont.showReadImages();
	//destroyAllWindows();

	DissimilarityMatrix dissMat = DissimilarityMatrix(imCont);
	dissMat.buildDissimilarity();

	Mat dm = dissMat.getDissimilarity();
	OrientedKruskal ok = OrientedKruskal(dissMat.getDissimilarity());

	vector<size_t> t = ok.getTree();

	cout << endl << "Dissimilarity matrix" << endl << dm << endl;
	double dt = (double)getTickCount();
	t = ok.solve();
	dt = ((double)getTickCount() - dt)/getTickFrequency();
	//cout << "Oriented Kruskal compute time: " << dt << endl << endl;

	ofstream f;
	ofstream mf;

	size_t root = -1;
	string resname(resultDir + "/result_" + testName);
	string matname(resultDir + "/matrix_" + testName);
	string listname(resultDir + "/namelist_" + testName);
	f.open(resname.c_str(), fstream::out);
	mf.open(matname.c_str(), fstream::out);

	mf << dm;

	//cout << "resname: " << resname << endl << endl;

	for(size_t i = 0; i < t.size(); i++) if(i == t[i]) root = i;
	f << t.size() << endl << (int)root << endl;

	//cout << endl;
	f << t[0];
	for(size_t i = 1; i < t.size(); i++){
		f << "," << t[i];
	}

	cout << (int)root << endl;

	cout << t[0];
	for(size_t i = 1; i < t.size(); i++){
		cout << "," << t[i];
	}

	cout << endl << endl;
	f.close();

	imCont.ListImageNames(listname);

	totaltime = ((double)getTickCount() - totaltime)/getTickFrequency();
	cout << "Total time: " << totaltime << endl << endl;

	return 0;
}
